"""
实体数据模型
"""

from typing import NamedTuple, List, Optional

import dataclasses

from .contants import ContratType, PositionSide


@dataclasses.dataclass
class AuthInfo:
    type: str = None

    def key(self) -> str:
        raise NotImplementedError


@dataclasses.dataclass
class ApiAuthInfo(AuthInfo):
    api_key: str = None
    api_secret: str = None
    type: str = dataclasses.field(default='api', init=False)

    def key(self):
        return f'{self.type}:{self.api_key}'


@dataclasses.dataclass
class OkxApiAuthInfo(ApiAuthInfo):
    api_passphrase: str = None


@dataclasses.dataclass
class DeribitOauthAuthInfo(AuthInfo):
    oauth_user_id: str = None
    type: str = dataclasses.field(default='oauth', init=False)

    def key(self):
        return f'{self.type}:{self.oauth_user_id}'


@dataclasses.dataclass
class IndexPair:
    base: str
    quote: str

    def __str__(self):
        return f'{self.base}-{self.quote}'

    def __repr__(self):
        return self.__str__()


@dataclasses.dataclass
class IndexPrice:
    # pair: str
    price: float
    # 单位为毫秒
    timestamp: int


@dataclasses.dataclass
class Ticker:
    mark_price: float
    timestamp: int

    index_price: float = None
    best_bid_price: float = None
    best_ask_price: float = None
    best_bid_size: float = None
    best_ask_size: float = None

    best_bid_iv: float = None
    best_ask_iv: float = None

    delta: float = None
    gamma: float = None
    theta: float = None
    vega: float = None


class OrderBookItem(NamedTuple):
    price: float
    size: float


@dataclasses.dataclass
class OrderBook:
    asks: List[OrderBookItem] = dataclasses.field(default_factory=lambda: [])
    bids: List[OrderBookItem] = dataclasses.field(default_factory=lambda: [])
    timestamp: int = None


@dataclasses.dataclass
class Instrument:
    instrument_id: str = None
    instrument_name: str = None
    exchange: str = None
    base_currency: str = None       # 基础币种
    quote_currency: str = None      # 计价币种
    counter_currency: str = None    # 计量币种
    margin_currency: str = None     # 保证金币种
    min_trade_size: float = None
    trade_size_step: float = None
    max_trade_size: float = None
    min_tick_size: float = None
    tick_size_step: float = None
    max_tick_size: float = None
    index_pair: IndexPair = None
    contract_multi: float = 1       # 张的乘数

    kind: str = None


@dataclasses.dataclass
class Spot(Instrument):
    kind: str = ContratType.Spot


@dataclasses.dataclass
class Future(Instrument):
    reversed: bool = None
    future_type: str = None         # Delivery / Perpetual
    expire_timestamp: int = None    # 单位为毫秒
    kind: str = ContratType.Future


@dataclasses.dataclass
class Option(Instrument):
    reversed: bool = None
    strike: float = None
    expire_timestamp: int = None
    option_type: str = None

    kind: str = ContratType.Option


@dataclasses.dataclass
class SimpleInstrument:
    instrument: str = None
    kind: str = None
    base_currency: str = None
    margin_currency: str = None
    reversed: Optional[bool] = None
    option_type: Optional[str] = None
    strike: Optional[float] = None
    expire_timestamp: Optional[int] = None


@dataclasses.dataclass
class CurrencySummary:
    base_currency: str = None
    margin_currency: str = None
    account_type: str = None

    equity: float = None
    equity_usd: float = None
    margin_balance: float = None    # 保证金余额

    mm: float = None
    im: float = None
    mm_ratio: float = None     # 维持保证金占比
    im_ratio: float = None     # 初始保证金占比

    is_cross: bool = False       # 是否跨币种模式
    is_pm: bool = False         # 是否组合保证金模式

    delta: float = 0
    gamma: float = 0
    theta: float = 0
    vega: float = 0


@dataclasses.dataclass
class AccountSummary:
    total_equity_usd: float = None
    summaries: List[CurrencySummary] = dataclasses.field(default_factory=lambda: [])


@dataclasses.dataclass
class Position:
    instrument: str = None
    size: float = None
    direction: str = None
    avg_price: float = None
    margin_mode: str = 'cross'    # 持仓模式，cross: 全仓 / isolated: 逐仓
    side: str = PositionSide.Both
    mark_price: float = None
    account_type: str = None

    im: float = None
    mm: float = None

    delta: float = None
    gamma: float = None
    vega: float = None
    theta: float = None


@dataclasses.dataclass
class Order:
    order_id: str = None
    instrument: str = None
    amount: float = None
    price: float = None
    direction: str = None
    filled_amount: float = None
    avg_price: float = None
    order_type: str = None
    label: str = None
    state: str = None
    time_in_force: str = 'GTC'
    reduce_only: bool = None
    post_only: bool = None
    create_timestamp: int = None
    update_timestamp: int = None
    account_type: str = None


@dataclasses.dataclass
class Trade:
    instrument: str = None
    order_id: str = None
    order_type: str = None
    trade_id: str = None
    timestamp: int = None
    price: float = None
    direction: str = None
    amount: float = None
    fee_currency: str = None
    fee: float = None
    mark_price: float = None


